package start

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"gitee.com/go-course/go11/devcloud-mini/cmdb/conf"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/logger"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/protocol"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/tracer"
	"gitee.com/go-course/go11/devcloud-mini/mcenter/clients/rpc"
	"github.com/infraboard/mcube/ioc"
	"github.com/spf13/cobra"

	// 把所有的业务模块全部加载
	_ "gitee.com/go-course/go11/devcloud-mini/cmdb/apps"
)

var (
	configType string
	configFile string
)

// root command
// vblog-api start
var Cmd = &cobra.Command{
	Use:   "start",
	Short: "vblog项目后端",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		// 1. 加载全局配置
		switch configType {
		case "env":
			_, err := conf.LoadConfigFromEnv()
			cobra.CheckErr(err)
		default:
			// 默认通过配置文件加载
			_, err := conf.LoadConfigFromToml(configFile)
			cobra.CheckErr(err)
		}

		// 2. 加载全局中间件配置(env)
		rpc.LoadClientFromEnv()

		// 3. 初始化全局Tracer对象
		tracer.InitTracer()

		// 启动Http协议服务器
		httpServer := protocol.NewHttp()
		go func() {
			herr := httpServer.Start()
			if herr != http.ErrServerClosed {
				cobra.CheckErr(herr)
			}
		}()

		//  启动GRPC server
		grpcServer := protocol.NewGrpc()
		go func() {
			gerr := grpcServer.Start()
			cobra.CheckErr(gerr)
		}()

		err := ioc.InitIocObject()
		cobra.CheckErr(err)

		// 信号处理 负责阻塞住主进行(Loop Os Signal)
		// 处理信号量
		ch := make(chan os.Signal, 1)
		// 如果os发出了信号后，会把该信号发往 ch channal
		signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGQUIT)

		// 从chanel中获取信号
		s := <-ch
		logger.L().Info().Msgf("receive os signal: %s, exit ...", s)

		// 做后续处理
		ctx := context.Background()
		httpServer.Stop(ctx)
		grpcServer.Stop(ctx)
	},
}

func init() {
	Cmd.Flags().StringVarP(&configType, "config-type", "t", "file", "程序加载配置的方式")
	Cmd.Flags().StringVarP(&configFile, "config-file", "f", "etc/config.toml", "配置文件的路径")
}
